Access violation v konstruktoru
Otázka od: Jaromir Cermak
22. 11. 2004 10:43
Ahoj vsichni
Mam nasledujici problem a zoufale prosim o pomoc. Vytvoril jsem si vlastni
formular s vlastnim konstruktorem. Jako prvni prikaz se vola inherited
create(AOwner) a ten zpusobi pad s AV.
Pri podrobnejsim krokovani pres unity delphi jsem si vsiml nasledujicich veci:
v unite system se jeste pred inherited vola funkce ClassCreate. V ni se
preskoci instrukce
CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance
v DL je hodnota 255
pri krokovani TCustomForm.Create mi to spadne na volani CreateNew(AOwner);
V konstruktoru jsem pouzival virtualni metodu, ale ani jeji odstraneni mi
nepomohlo. Nevite kde delam chybu? Prosim poradte.
Jaromir Cermak
Odpovedá: Petr Brant
22. 11. 2004 12:11
Formulare s vlastnim konstruktorem tvorim casto a bez problemu. Ale namisto
AOwner pisu nil:
constructor TActivityWnd.Create(VehTable: TTable; FBWrap: TFBWrap;
MapBinWork: TMapBinWork2);
begin
inherited Create(nil);
VehIDList:= TIntegerList.Create;
self.VehTable:= VehTable;
self.FBWrap:= FBWrap;
self.MapBinWork:= MapBinWork;
....
a vyvolani formulare delam takto:
ActivityWnd:= TActivityWnd.Create(VehTable, FBWrap, MapBinWork);
ActivityWnd.ShowModal;
ActivityWnd.Free;
Zkus to take tak, nikdy jsem s tim problemy nemel.
RNDr. Petr Brant [brant@dcomm.cz]
http://brant.wz.cz
Mam nasledujici problem a zoufale prosim o pomoc. Vytvoril jsem si vlastni
formular s vlastnim konstruktorem. Jako prvni prikaz se vola inherited
create(AOwner) a ten zpusobi pad s AV.
Pri podrobnejsim krokovani pres unity delphi jsem si vsiml nasledujicich
veci:
v unite system se jeste pred inherited vola funkce ClassCreate. V ni se
preskoci instrukce
CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance
v DL je hodnota 255
pri krokovani TCustomForm.Create mi to spadne na volani CreateNew(AOwner);
V konstruktoru jsem pouzival virtualni metodu, ale ani jeji odstraneni mi
nepomohlo. Nevite kde delam chybu?
Odpovedá: Jaromir Cermak
22. 11. 2004 12:12
Taky to neni poprve co delam vlastni konstruktor, spis premyslim proc se
preskoci instrukce
CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance.
Zaujalo me ze v registru DL je 255. Probehne li vse normalne, je tam 1.
Ale mozna ze premyslim scestne a jeno neco nevidim. Nevite na co si dat pozor?
Jaromir Cermak
Odpovedá: Petr Fejfar
22. 11. 2004 12:30
Jaromir Cermak wrote:
> Taky to neni poprve co delam vlastni konstruktor, spis premyslim proc
> se preskoci instrukce
Mohl bys pls specifikovat, co mas na mysli tim "preskoci se"?
To jako ze ti debugger ukaze, ze instrukci vykonavana, ale zadna subrutina
se
nezavola?
V tom pripade bych rek, ze debugger ukazuje buhvi co resp.
ze mapa cisel radku z prekladu neodpovida trasovanemu zdrojovemu kodu.
pf
Odpovedá: delphin@post.cz
22. 11. 2004 13:00
> Taky to neni poprve co delam vlastni konstruktor, spis premyslim proc se
preskoci instrukce
> CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance.
> Zaujalo me ze v registru DL je 255. Probehne li vse normalne, je tam 1.
Konstruktor je fyzicky: inicialize tridy + metoda + volani
AfterConstruction. Pri volani prvniho konstruktoru se konstruktor vola
normalne, tedy vcetne inicializace a AfterConstruction. Pokud se z
konstruktoru vola konstruktor predka, nevola se uz jako konstruktor, ale
jako standardni procedura. V DL se predava specialni parametr, ktery
rozhoduje o tom, zda se vola jako konstruktor nebo jako metoda.
Odpovedá: Jaromir Cermak
22. 11. 2004 13:49
Ne.
ve funkci:
function _ClassCreate(AClass: TClass; Alloc: Boolean): TObject;
asm
{ -> EAX = pointer to VMT }
{ <- EAX = pointer to instance }
PUSH EDX
PUSH ECX
PUSH EBX
TEST DL,DL
JL @@noAlloc
CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance
@@noAlloc:
z unity systeM se po instrukci TEST provede JL ktery dany CALL preskoci.
Debugger ukazuje ze DL=255, u formulare kde je vsechno v poradku DL=1. Nevim
proc k tomu dojde.
Konstruktor vypada takto:
constructor TFORP_EditProtokol.CreateEditProtokol(AOwner:TComponent;
DS:TDataSet;NazRadku:String);
begin
inherited Create(nil{AOwner});
if DS<>nil then
begin
dsRad.DataSet:=DS;
FBeforePost:=DS.BeforePost;
//DS.BeforePost:=cdsRad.BeforePost;
FPocZmen:=(DS as TClientDataSet).ChangeCount;
if DS.Active then
begin
DS.First;
while not DS.Eof do
begin
VytvorRadek(DS);
DS.Next;
end;
DS.First;
end;
end;
end;
metoda VytvorRadek je virtualni, ale i kdyz tam nebyla tak to padalo.
Jaromir Cermak
-----Original Message-----
From: Petr Fejfar [mailto:development@callnet.cz]
Sent: Monday, November 22, 2004 12:25 PM
To: delphi-l@clexpert.cz
Subject: Re: Access violation v konstruktoru
Jaromir Cermak wrote:
> Taky to neni poprve co delam vlastni konstruktor, spis premyslim proc
> se preskoci instrukce
Mohl bys pls specifikovat, co mas na mysli tim "preskoci se"?
To jako ze ti debugger ukaze, ze instrukci vykonavana, ale zadna subrutina
se
nezavola?
Odpovedá: Petr Fejfar
22. 11. 2004 14:13
Jaromir Cermak wrote:
> constructor TFORP_EditProtokol.CreateEditProtokol(AOwner:TComponent;
> DS:TDataSet;NazRadku:String);
> begin
> inherited Create(nil{AOwner});
>
> if DS<>nil then
> begin
> dsRad.DataSet:=DS;
> FBeforePost:=DS.BeforePost;
> //DS.BeforePost:=cdsRad.BeforePost;
> FPocZmen:=(DS as TClientDataSet).ChangeCount;
> if DS.Active then
> begin
> DS.First;
> while not DS.Eof do
> begin
> VytvorRadek(DS);
> DS.Next;
> end;
> DS.First;
> end;
> end;
> end;
Ne ze bych ve tvem kodu videl co je spatne, ale obecne bych rekl,
ze tento chyb se vyskytuje "nechtenym" spustenim nejake event
mimo kontext tj. v dobe, kdy jeste neni konstrukce/inicializace
dokoncena popr. kdy nejsou predany vsechny argumenty,
jejich nespravne poradi apod.
***
Napada me - nezpusti se ti nejaka event - treba pri prirazeni
dsRad.DataSet:=DS; ?
HTH, pf
Odpovedá: Jaromir Cermak
22. 11. 2004 14:12
Uz jsem vyradil z constructoru vsechno, zustal jen radek s inherited, ale porad
to pada. Nemuze byt problem v .dfm. Na co se zamerit?
Jaromir Cermak
-----Original Message-----
From: Petr Fejfar [mailto:development@callnet.cz]
Sent: Monday, November 22, 2004 1:25 PM
To: delphi-l@clexpert.cz
Subject: Re: Access violation v konstruktoru
Jaromir Cermak wrote:
> constructor TFORP_EditProtokol.CreateEditProtokol(AOwner:TComponent;
> DS:TDataSet;NazRadku:String);
> begin
> inherited Create(nil{AOwner});
>
> if DS<>nil then
> begin
> dsRad.DataSet:=DS;
> FBeforePost:=DS.BeforePost;
> //DS.BeforePost:=cdsRad.BeforePost;
> FPocZmen:=(DS as TClientDataSet).ChangeCount;
> if DS.Active then
> begin
> DS.First;
> while not DS.Eof do
> begin
> VytvorRadek(DS);
> DS.Next;
> end;
> DS.First;
> end;
> end;
> end;
Odpovedá: Petr Fejfar
22. 11. 2004 14:21
Jaromir Cermak wrote:
> Uz jsem vyradil z constructoru vsechno, zustal jen radek s inherited,
> ale porad to pada. Nemuze byt problem v .dfm. Na co se zamerit?
Pokud jsi ten formular vytvoril rucnim zkopirovanim mimo IDE,
tak snad jen zkontrolovat, jestli je definovan v .DFM jako potomek,
napr.
inherited XHGBasalForm: TXHGBasalForm
Normalne je tam object, napr.
object BIZAbstractForm: TBIZAbstractForm
BTW, predpokladam, ze dedis z TForm
pf
Odpovedá: Jaromir Cermak
24. 11. 2004 7:50
Jeste se vracim k problemu z pondelka.
Mam formular, ktery pri vytvareni v jistem kontextu generuje access violation.
Situace: Je- li vytvoren z nemodalniho okna => nespadne
V realnem umisteni: Volan jako treti vnorene modalni okno, pada spolehlive. Na
prikazu CreateNew(AOwner); konstruktoru TCustomForm.Create(nil).
Vyradil jsem i svuj vlastni konstruktor, abych to vyzkousel a vysledkem je ze
to furt pada.
Jaromir Cermak